﻿using System;
using System.Collections.Generic;
using System.Drawing;
using Autodesk.Revit.DB;
using YJKArchMethodLibrary.Utils;

namespace BuildingOutLine.BuildingOutLine.Triangulation
{
	public class TriangulationKit
	{
		public static void CalculateTriangulation(List<XYZ> points, ref List<EdgeInfo> edgeInfos)
		{
			List<TriangleVertex> triVertexes = new List<TriangleVertex>();
			List<TriangleEdge> tempTriEdges = new List<TriangleEdge>();
			List<Triangle> list = new List<Triangle>();
			TriangulationKit.BuildTriangles(points, ref triVertexes, ref tempTriEdges, ref list);
			TriangulationKit.BuildDelaunay(triVertexes, tempTriEdges, list);
			List<TriangleEdge> edges = Triangle.GetEdges(list);
			if (edges.Count == 0)
			{
				return;
			}
			TriangleEdge.GetUniqueEdges(ref edges);
			foreach (TriangleEdge triangleEdge in edges)
			{
				XYZ startPoint = new XYZ((double)triangleEdge.StartPoint.Point.X, (double)triangleEdge.StartPoint.Point.Y, 0.0);
				XYZ endPoint = new XYZ((double)triangleEdge.EndPoint.Point.X, (double)triangleEdge.EndPoint.Point.Y, 0.0);
				EdgeInfo item = new EdgeInfo(startPoint, endPoint, 0.0);
				edgeInfos.Add(item);
			}
		}

		private static void BuildTriangles(List<XYZ> points, ref List<TriangleVertex> triVertexes, ref List<TriangleEdge> tempTriEdges, ref List<Triangle> triangleList)
		{
			for (int i = 0; i < points.Count; i++)
			{
				TriangleVertex triangleVertex = new TriangleVertex();
				triangleVertex.Point = new PointF((float)points[i].X, (float)points[i].Y);
				triangleVertex.ID = i + 1;
				triVertexes.Add(triangleVertex);
			}
			int num = 0;
			double num2 = double.MaxValue;
			foreach (TriangleVertex triangleVertex2 in triVertexes)
			{
				double num3 = TriangleEdge.LengthSquare(triVertexes[0], triangleVertex2);
				if (num3 != 0.0 && num3 < num2)
				{
					num = triangleVertex2.ID;
					num2 = num3;
				}
			}
			TriangleVertex triangleVertex3 = triVertexes[0];
			TriangleVertex triangleVertex4 = triVertexes[num - 1];
			if (triangleVertex3 != null && triangleVertex4 != null)
			{
				TriangleEdge edge = new TriangleEdge(triangleVertex3, triangleVertex4);
				TriangleVertex bestPoint = TriangleEdge.GetBestPoint(edge, triVertexes);
				if (bestPoint != null)
				{
					TriangleEdge triangleEdge = new TriangleEdge(triangleVertex3, bestPoint);
					TriangleEdge triangleEdge2 = new TriangleEdge(bestPoint, triangleVertex4);
					TriangleEdge triangleEdge3 = new TriangleEdge(triangleVertex4, triangleVertex3);
					Triangle triangle = new Triangle(triangleVertex3, bestPoint, triangleVertex4);
					triangle.Edge1 = triangleEdge;
					triangle.Edge2 = triangleEdge2;
					triangle.Edge3 = triangleEdge3;
					triangleEdge.LeftTriangle = triangle;
					triangleEdge2.LeftTriangle = triangle;
					triangleEdge3.LeftTriangle = triangle;
					tempTriEdges.Add(triangleEdge);
					tempTriEdges.Add(triangleEdge2);
					tempTriEdges.Add(triangleEdge3);
					triangleList.Add(triangle);
					return;
				}
				edge = new TriangleEdge(triangleVertex4, triangleVertex3);
				bestPoint = TriangleEdge.GetBestPoint(edge, triVertexes);
				if (bestPoint != null)
				{
					TriangleEdge triangleEdge4 = new TriangleEdge(triangleVertex4, bestPoint);
					TriangleEdge triangleEdge5 = new TriangleEdge(bestPoint, triangleVertex3);
					TriangleEdge triangleEdge6 = new TriangleEdge(triangleVertex3, triangleVertex4);
					Triangle triangle2 = new Triangle(triangleVertex4, bestPoint, triangleVertex3);
					triangle2.Edge1 = triangleEdge4;
					triangle2.Edge2 = triangleEdge5;
					triangle2.Edge3 = triangleEdge6;
					triangleEdge4.LeftTriangle = triangle2;
					triangleEdge5.LeftTriangle = triangle2;
					triangleEdge6.LeftTriangle = triangle2;
					tempTriEdges.Add(triangleEdge4);
					tempTriEdges.Add(triangleEdge5);
					tempTriEdges.Add(triangleEdge6);
					triangleList.Add(triangle2);
				}
			}
		}

		private static void BuildDelaunay(List<TriangleVertex> triVertexes, List<TriangleEdge> tempTriEdges, List<Triangle> triangleList)
		{
			while (tempTriEdges.Count != 0)
			{
				TriangleEdge triangleEdge = tempTriEdges[0];
				TriangleVertex triangleVertex = new TriangleVertex();
				triangleVertex = TriangleEdge.GetBestPoint(triangleEdge, triVertexes);
				if (triangleVertex != null)
				{
					Triangle triangle = new Triangle(triangleEdge.StartPoint, triangleVertex, triangleEdge.EndPoint);
					TriangleEdge triangleEdge2 = new TriangleEdge(triangleEdge.StartPoint, triangleVertex);
					TriangleEdge triangleEdge3 = new TriangleEdge(triangleVertex, triangleEdge.EndPoint);
					TriangleEdge triangleEdge4 = new TriangleEdge(triangleEdge.EndPoint, triangleEdge.StartPoint);
					triangleEdge2.LeftTriangle = triangle;
					triangleEdge3.LeftTriangle = triangle;
					triangleEdge4.LeftTriangle = triangle;
					triangle.Edge1 = triangleEdge2;
					triangle.Edge2 = triangleEdge3;
					triangle.Edge3 = triangleEdge4;
					triangleEdge4.RightTriangle = triangleEdge.LeftTriangle;
					triangleEdge.RightTriangle = triangleEdge4.LeftTriangle;
					tempTriEdges.Remove(triangleEdge);
					triangleList.Add(triangle);
					TriangleEdge triangleEdge5 = new TriangleEdge();
					triangleEdge5.StartPoint = triangleEdge2.EndPoint;
					triangleEdge5.EndPoint = triangleEdge2.StartPoint;
					TriangleEdge triangleEdge6 = TriangleEdge.FindSameEdge(tempTriEdges, triangleEdge5);
					if (triangleEdge6 == null)
					{
						tempTriEdges.Add(triangleEdge2);
					}
					else
					{
						tempTriEdges.Remove(triangleEdge6);
					}
					triangleEdge5.StartPoint = triangleEdge3.EndPoint;
					triangleEdge5.EndPoint = triangleEdge3.StartPoint;
					triangleEdge6 = TriangleEdge.FindSameEdge(tempTriEdges, triangleEdge5);
					if (triangleEdge6 == null)
					{
						tempTriEdges.Add(triangleEdge3);
					}
					else
					{
						tempTriEdges.Remove(triangleEdge6);
					}
				}
				else
				{
					tempTriEdges.Remove(triangleEdge);
				}
			}
		}
	}
}
